#include <map>
#include "BaselineRandomWalk.h"
#include "Lottery.h"

using namespace std;

class LearnedModel : public LotteryRandomWalk
{
public:
    LearnedModel(API *network) : LotteryRandomWalk(network) {}
    void learnParams(); //populate params
    void loadParams(char *fname);
    void saveParams(char *fname);

protected:
    virtual void updateDiscoveredNode(int discoveredNode);

    // Learned parameters
    /*
    struct KEY {
        KEY() {}
        KEY(TIntPr degree, TIntPr degreeExplored) :
            deg(degree), degExplored(degreeExplored) {}
        TIntPr deg, degExplored;
        bool operator < (const KEY &r) const {
            return (deg.Val1 == r.deg.Val1)? ((deg.Val2 == r.deg.Val2)?
                ((degExplored.Val1 == r.degExplored.Val1)? 
                (degExplored.Val2 < r.degExplored.Val2) : 
                degExplored.Val1 < r.degExplored.Val1
                ) : deg.Val2 < r.deg.Val2
                ) : deg.Val1 < r.deg.Val1;
        }
    };
    */
    struct KEY {
        KEY() {}
        KEY(TIntPr degree, TIntPr degreeExplored) {
            degDiff = TIntPr(degree.Val1 - degreeExplored.Val1,
                degree.Val2 - degreeExplored.Val2);
        }
        TIntPr degDiff;
        bool operator < (const KEY &r) const {
            return degDiff < r.degDiff;
        }
    };
    double getScore(TIntPr gain) { return gain.Val1*coeffIn + gain.Val2*coeffOut;}

    //hash<degIn, degOut, degInFromExplored, degOutToExplored> -> Gain
    map<KEY, double> params;
    double sumNormalizer, nodeNormalizer, sampleCount, delta, unknownScore;
    double coeffIn, coeffOut;
};
